package dao

import (
	"fmt"
	"time"

	"github.com/ammyhaber/seckill/service/inventory/model"
	"github.com/jmoiron/sqlx"
)

// InventoryLockDAO 库存锁定记录数据访问对象
type InventoryLockDAO struct {
	db *sqlx.DB
}

// NewInventoryLockDAO 创建库存锁定DAO
func NewInventoryLockDAO(db *sqlx.DB) *InventoryLockDAO {
	return &InventoryLockDAO{
		db: db,
	}
}

// CreateLock 创建库存锁定记录
func (d *InventoryLockDAO) CreateLock(orderID string, productID int64, count int) error {
	now := time.Now()
	sql := `INSERT INTO inventory_lock 
		(order_id, product_id, count, status, lock_time, created_at, updated_at)
		VALUES (?, ?, ?, ?, ?, ?, ?)`

	_, err := d.db.Exec(sql, orderID, productID, count, model.LockStatusLocked, now, now, now)
	return err
}

// CreateLockWithTx 使用事务创建库存锁定记录
func (d *InventoryLockDAO) CreateLockWithTx(tx *sqlx.Tx, orderID string, productID int64, count int) error {
	now := time.Now()
	sql := `INSERT INTO inventory_lock 
		(order_id, product_id, count, status, lock_time, created_at, updated_at)
		VALUES (?, ?, ?, ?, ?, ?, ?)`

	_, err := tx.Exec(sql, orderID, productID, count, model.LockStatusLocked, now, now, now)
	return err
}

// ConfirmLock 确认库存锁定
func (d *InventoryLockDAO) ConfirmLock(orderID string, productID int64) error {
	now := time.Now()
	sql := `UPDATE inventory_lock 
		SET status = ?, confirm_time = ?, updated_at = ?
		WHERE order_id = ? AND product_id = ? AND status = ?`

	result, err := d.db.Exec(sql, model.LockStatusConfirmed, now, now, orderID, productID, model.LockStatusLocked)
	if err != nil {
		return err
	}

	affected, err := result.RowsAffected()
	if err != nil {
		return err
	}

	if affected == 0 {
		return fmt.Errorf("找不到有效的锁定记录: orderID=%s, productID=%d", orderID, productID)
	}

	return nil
}

// ConfirmLockWithTx 使用事务确认库存锁定
func (d *InventoryLockDAO) ConfirmLockWithTx(tx *sqlx.Tx, orderID string, productID int64) error {
	now := time.Now()
	sql := `UPDATE inventory_lock 
		SET status = ?, confirm_time = ?, updated_at = ?
		WHERE order_id = ? AND product_id = ? AND status = ?`

	result, err := tx.Exec(sql, model.LockStatusConfirmed, now, now, orderID, productID, model.LockStatusLocked)
	if err != nil {
		return err
	}

	affected, err := result.RowsAffected()
	if err != nil {
		return err
	}

	if affected == 0 {
		return fmt.Errorf("找不到有效的锁定记录: orderID=%s, productID=%d", orderID, productID)
	}

	return nil
}

// CancelLock 取消库存锁定
func (d *InventoryLockDAO) CancelLock(orderID string, productID int64) error {
	now := time.Now()
	sql := `UPDATE inventory_lock 
		SET status = ?, cancel_time = ?, updated_at = ?
		WHERE order_id = ? AND product_id = ? AND status = ?`

	result, err := d.db.Exec(sql, model.LockStatusCanceled, now, now, orderID, productID, model.LockStatusLocked)
	if err != nil {
		return err
	}

	affected, err := result.RowsAffected()
	if err != nil {
		return err
	}

	if affected == 0 {
		return fmt.Errorf("找不到有效的锁定记录: orderID=%s, productID=%d", orderID, productID)
	}

	return nil
}

// CancelLockWithTx 使用事务取消库存锁定
func (d *InventoryLockDAO) CancelLockWithTx(tx *sqlx.Tx, orderID string, productID int64) error {
	now := time.Now()
	sql := `UPDATE inventory_lock 
		SET status = ?, cancel_time = ?, updated_at = ?
		WHERE order_id = ? AND product_id = ? AND status = ?`

	result, err := tx.Exec(sql, model.LockStatusCanceled, now, now, orderID, productID, model.LockStatusLocked)
	if err != nil {
		return err
	}

	affected, err := result.RowsAffected()
	if err != nil {
		return err
	}

	if affected == 0 {
		return fmt.Errorf("找不到有效的锁定记录: orderID=%s, productID=%d", orderID, productID)
	}

	return nil
}

// GetLockByOrderAndProduct 获取特定订单和商品的锁定记录
func (d *InventoryLockDAO) GetLockByOrderAndProduct(orderID string, productID int64) (*model.InventoryLock, error) {
	sql := `SELECT id, order_id, product_id, count, status, lock_time, confirm_time, cancel_time, created_at, updated_at 
		FROM inventory_lock 
		WHERE order_id = ? AND product_id = ?`

	var lock model.InventoryLock
	err := d.db.Get(&lock, sql, orderID, productID)
	if err != nil {
		if err.Error() == "sql: no rows in result set" {
			return nil, nil
		}
		return nil, err
	}

	return &lock, nil
}

// GetLocksByProductID 获取特定商品的所有锁定记录
func (d *InventoryLockDAO) GetLocksByProductID(productID int64, status model.LockStatus) ([]*model.InventoryLock, error) {
	sql := `SELECT id, order_id, product_id, count, status, lock_time, confirm_time, cancel_time, created_at, updated_at 
		FROM inventory_lock 
		WHERE product_id = ? AND status = ?`

	var locks []*model.InventoryLock
	err := d.db.Select(&locks, sql, productID, status)
	if err != nil {
		return nil, err
	}

	return locks, nil
}

// GetExpiredLocks 获取超时未确认的锁定记录
func (d *InventoryLockDAO) GetExpiredLocks(expireTime time.Time) ([]*model.InventoryLock, error) {
	sql := `SELECT id, order_id, product_id, count, status, lock_time, confirm_time, cancel_time, created_at, updated_at 
		FROM inventory_lock 
		WHERE status = ? AND lock_time < ?`

	var locks []*model.InventoryLock
	err := d.db.Select(&locks, sql, model.LockStatusLocked, expireTime)
	if err != nil {
		return nil, err
	}

	return locks, nil
}
